/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.model.domain.proceso.envio.subida.xml;

import com.model.dao.mapping.Enaho;
import com.model.domain.persona.HogarXml;
import com.model.domain.ubicacion.ViviendaMarcoXml;
import com.model.domain.ubicacion.ViviendaXml;
import util.file.xml.TablaXml;
import util.file.xml.RegistroXml;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import util.file.xml.ArchivoXml;

/**
 *
 * @author Rdelacruz
 */
public abstract class ArchivoXmlEnaho 
{
    private final ArchivoXml archivoXml;
    private TipoArchivoXmlEnaho tipo;
    private Map<String,Node> mNodosTabla;
    
    //public void parsear(TablaXml<RegistroXml> tabla, Node nTabla) throws Exception;    
    protected abstract Map<String,Node> calcularNodosTabla() throws Exception;
    
    protected ArchivoXmlEnaho(ArchivoXml archivoXml) {
        this.archivoXml = archivoXml;
    }    
    
    public static ArchivoXmlEnaho parsear(ArchivoXml archivoXml) {
        Document doc = archivoXml.getDocument();
        Element eRaiz = doc.getDocumentElement();
        String s = eRaiz.getNodeName();
        
        ArchivoXmlEnaho archivo = null;        
        TipoArchivoXmlEnaho tipo;
        if(s.equals("Marco")) {
            tipo = TipoArchivoXmlEnaho.MARCO;
            archivo = new MarcoXmlEnaho(archivoXml);            
        }
        else if(s.equals("TABLAS")) {
            tipo = TipoArchivoXmlEnaho.CAMPO;
            archivo = new CampoXmlEnaho(archivoXml);
        }
        else {
            tipo = TipoArchivoXmlEnaho.OTRO;  
        }        
        //XmlUtil.getPrimerNodo();
        //NodeList lnTags = xmlDoc.getElementsByTagName(tag);//lista de nodos Tag
        //Node nTag = lnTags.item(0);//Primer nodo Tag 
        
        if(archivo!=null)
            archivo.setTipo(tipo);
        
        return archivo; 
    }
       
   
    /**
     * 
     * @param <R>
     * @param txml
     * @param nombreTablaXml
     * @return 
     * true: "tablaXml" existe en el XML y fue parseada. 
     * false: no existe y no fue parseada
     * @throws Exception 
     */
    public final <R extends RegistroXml> boolean parsear(TablaXml<R> txml, String nombreTablaXml) throws Exception {
        Map<String,Node> nodosTabla = getNodosTabla();
        Node nodoTabla = nodosTabla.get(nombreTablaXml);
                
        if(nodoTabla==null) {//no existe tabla en XML. esto no es error porque 
                             //los XML no contienen todas las tablas necesariamente
            txml.setNombre(nombreTablaXml);
            return false;
        }
        else {        
            Class claseInstancia = RegistroXml.class;
            
            switch(this.getTipo()) {
                case CAMPO:
                    if(Enaho.HOGAR.getTabla().equals(nombreTablaXml))
                        claseInstancia = HogarXml.class;                
                    else if(Enaho.VIVIENDA.getTabla().equals(nombreTablaXml))
                        claseInstancia = ViviendaXml.class;
                    else
                        claseInstancia = RegistroXmlHogar.class;
                    break;
                case MARCO:   
                    if(Enaho.VIVIENDA_MARCO.getTabla().equals(nombreTablaXml))
                        claseInstancia = ViviendaMarcoXml.class;
                    break;
            }
            
            txml.parsear(nodoTabla,"Registro",claseInstancia);
            return true;
        }        
    }     
    
    public Node getNodoTabla(String tablaXml) throws Exception {
        return getNodosTabla().get(tablaXml);
    }
    
    public final Map<String,Node> getNodosTabla() throws Exception {
        if(mNodosTabla==null) {
            mNodosTabla = calcularNodosTabla();
        }
        return mNodosTabla;
    }
    
    
 

    public TipoArchivoXmlEnaho getTipo() {
        return tipo;
    }

    public void setTipo(TipoArchivoXmlEnaho tipo) {
        this.tipo = tipo;
    }

    public ArchivoXml getArchivoXml() {
        return archivoXml;
    }



    
}
